﻿//
//  Monkey Manager
//  Copyright (C) 2010 Victor Tereschenko (aka sibvic)
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//     
// ========================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Forms;
using MonkeyManager.Command;
using ManagerDB;
using MonkeyManager.FilterPanels;
using MonkeyManager.DataProvider;

namespace MonkeyManager
{
    /// <summary>
    /// Interaction logic for ManagerWindow.xaml
    /// </summary>
    public partial class ManagerWindow : Window
    {
        IDatabase mDatabase;
        public ManagerWindow()
        {
            InitializeComponent();

            grid.RowDefinitions[1].Height = new GridLength(0);

            mController = new Controller();
            filterPanel.Children.Add(new TextFilter(mFilter));
            filterPanel.Children.Add(new TagFilter(mFilter));
            filterPanel.Children.Add(new SortColumnSelector(mFilter));
            filterPanel.Children.Add(new WatchedStatusSelector(mFilter));
            filterPanel.Children.Add(new SortTypeSelector(mFilter));
            filterPanel.Children.Add(new FileStatusSelector(mFilter));
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                mDatabase = DatabaseFactory.Create(mController.Options);
                mDataProvider = new DelayProvider(mDatabase);
                mDataProvider.Callback += new RequestCompleteDelegate(mDataProvider_Callback);
                mDataProvider.Request(mFilter);
                mFilter.OnFilterChanged += new FilterChanged(onFilterChanged);

                Title = mController.Options.DBName;
            }
            catch (NotSupportedDatabse ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                Close();
            }
        }
        
        void mDataProvider_Callback(StoredFile[] files)
        {
            mFiles = files;
            Dispatcher.Invoke((Action)(() =>
            {
                filesList.Items.Clear();
                foreach (StoredFile file in mFiles)
                    filesList.Items.Add(file);    
            }));
        }

        DelayProvider mDataProvider;
        PlayersController mPlayerController = new PlayersController();
        Controller mController;
        StoredFile[] mFiles;
        Filter mFilter = new Filter();

        #region Helpers
        /// <summary>
        /// Gets list of selected files.
        /// </summary>
        /// <returns>Array of files or empty array.</returns>
        private StoredFile[] getSelectedFiles()
        {
            List<StoredFile> list = new List<StoredFile>();
            foreach (object item in filesList.SelectedItems)
            {
                StoredFile file = (StoredFile)item;
                if (file == null)
                    continue;
                list.Add(file);
            }

            return list.ToArray();
        }
        #endregion

        private void onFilterChanged()
        {
            mDataProvider.Request(mFilter);
        }

        private void infoButton_Click(object sender, RoutedEventArgs e)
        {
            foreach (object item in filesList.SelectedItems)
            {
                StoredFile file = (StoredFile)filesList.SelectedItem;
                if (file == null)
                    continue;
                InfoWindow window = new InfoWindow(file, true, mDatabase);
                window.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
                window.Owner = this;
                window.Show();
            }
        }

        private void playButton_Click(object sender, RoutedEventArgs e)
        {
            StoredFile[] files = getSelectedFiles();
            if (files.Length == 0)
                return;
            PlayerWindow player = new PlayerWindow(new FilesSource(files), mDatabase, mPlayerController);
            player.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
            player.Owner = this;
            player.Show();
        }

        private void filesList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            StoredFile file = (StoredFile)filesList.SelectedItem;
            if (file == null)
                return;
            InfoWindow window = new InfoWindow(file, true, mDatabase);
            window.WindowStartupLocation = System.Windows.WindowStartupLocation.Manual;
            Point mousePosition = e.MouseDevice.GetPosition(null);

            window.Top = this.Top + mousePosition.Y;
            window.Left = this.Left + mousePosition.X;
            window.Owner = this;
            window.Show();
        }

        private void onAutotag_Click(object sender, RoutedEventArgs e)
        {
            StoredFile[] files = getSelectedFiles();
            if (files.Length == 0)
                return;
            AutotagCommand command = new AutotagCommand(files, mDatabase);
            var strategy = new AutotagCommandStrategy(command, this);
            mController.CommandExecutor.Execute(command);
        }

        private void onDeleteFile_Click(object sender, RoutedEventArgs e)
        {
            if (System.Windows.MessageBox.Show("Are you sure?", "Delete selected files?", System.Windows.MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;
            foreach (object item in filesList.SelectedItems)
            {
                StoredFile file = (StoredFile)item;
                if (file == null)
                    continue;

                try
                {
                    string fileToDelete = mDatabase.GetPath(file);
                    System.IO.FileAttributes attrs = System.IO.File.GetAttributes(fileToDelete);
                    if (attrs.HasFlag(System.IO.FileAttributes.ReadOnly))
                        System.IO.File.SetAttributes(fileToDelete, System.IO.FileAttributes.Normal);
                    System.IO.File.Delete(fileToDelete);
                    file.File.FileName = "";
                }
                catch
                {
                    continue;
                }
                mDatabase.Update(file);
            }
            mDataProvider.Request(mFilter);
        }

        private void onMarkAsWatched_Click(object sender, RoutedEventArgs e)
        {
            if (System.Windows.MessageBox.Show("Are you sure?", "Mark selected as watched?", System.Windows.MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            foreach (object item in filesList.SelectedItems)
            {
                StoredFile file = (StoredFile)item;
                if (file == null)
                    continue;

                file.File.Count = 1.0;
                mDatabase.Update(file);
            }
            mDataProvider.Request(mFilter);
        }

        private void onRemove_Click(object sender, RoutedEventArgs e)
        {
            if (System.Windows.MessageBox.Show("Are you sure?", "Remove completely?", System.Windows.MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            foreach (object item in filesList.SelectedItems)
            {
                StoredFile file = (StoredFile)item;
                if (file == null)
                    continue;

                if (mDatabase is IMutableDatabase)
                    (mDatabase as IMutableDatabase).Remove(file);
            }
            mDataProvider.Request(mFilter);
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            mDatabase.Dispose();
            mDataProvider.Dispose();
            mController.Dispose();
            mController = null;
        }

        private void playRandomButton_Click(object sender, RoutedEventArgs e)
        {
            PlayerWindow player = new PlayerWindow(new RandomFileSource(mDatabase, mFilter), mDatabase, mPlayerController);
            player.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
            player.Owner = this;
            player.Show();
        }

        private void addButton_Click(object sender, RoutedEventArgs e)
        {
            var process = new System.Diagnostics.ProcessStartInfo("AddManager.exe");
            process.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
            System.Diagnostics.Process.Start(process);
        }
    }
}
